# ingamestate.rb
# created by: Dan Alexander
# date: 3/6/2011
# license: New BSD License
#
# InGameState
# The ingame state, inherited from gamestate.

include Rubygame
require "io/wait"

class InGameState < GameState

	attr_accessor :server_running
	attr_accessor :loggedin
	attr_accessor :got_response
	
	def initialize(scr)
		super(scr) #GameState parent class initialize

		@in_move = false
		
		@loggedin = false
		@got_response = false
		
		#start the listening thread
		@send_message = ""
		@slp = 0
		
		@server_running = false
		
		@player_stats = Hash.new
		
		server_start
		
		#create the tile engine
		@map = Map.new()
		
		#set up fonts
		TTF.setup
		@fontStats = TTF.new "resources/font.ttf", 14
		
		@attempt_move = Array.new
		@attempt_move[0] = 0
		@attempt_move[1] = 0
	end
	
	def server_start
		host = $hostname
		port = $port
		begin
			@server = TCPSocket.open(host,port)
			@server_running = true
			if $debug then puts "starting thread..." end
			listen = Thread.new {listen_to_server()}
			return
		rescue
			if $debug then puts "Could not connect to service." end
			@server_running = false
			return
		end
	end
	
	#this is a thread that listens to the server
	def listen_to_server
	
		if $debug then puts "STARTED LISTENING THREAD..." end
		if $debug then puts "listening to " + $hostname + " on port " + $port.to_s() + "..." end	
		
		while $should_run == true do
			message = ""
			#keep reading until newline to get the entire message
			if @server.ready?
				while line = @server.getc do
					#puts line
					if line == "\n" then break end
					message += line
				end
				
				#we have the message, so do something about it
				if message != ""
					if $debug then puts message end
					#msg = Hash.new
					msg = JSON.parse(message)
					time = Time.now
					if msg["message_id"] == "dungeon_map"
						if $debug then puts "GOT MAP RESPONSE FROM SERVER..." end
						@map.load_json_map(message)
					elsif msg["message_id"] == "login_response"
						if $debug then puts "got log in response..." end
						result = msg["success"]
						@loggedin = result
						#if $debug then puts "Got login response: " + @loggedin end
						@got_response = true						
						if $debug then puts "got_response: " + @got_response.to_s() end
						
					elsif msg["message_id"] == "move_response"
						result = msg["success"]
						if result == true
							@map.player["x"] = Integer(@map.player["x"]) + @attempt_move[0]
							@map.player["y"] = Integer(@map.player["y"]) + @attempt_move[1]
							@attempt_move[0] = 0
							@attempt_move[1] = 0
						end
						@in_move = false
					elsif msg["message_id"] == "party"
						if $debug then puts "got party update." end
						@map.players = msg["players"]
					elsif msg["message_id"] == "monsters"
					  @map.monsters = msg["monsters"]
					elsif msg["message_id"] == "inventory"
					
					elsif msg["message_id"] == "dungeon_items"
					
					elsif msg["message_id"] == "stats"
						#puts msg["stats"]
						@player_stats = msg["stats"]
						#@player_stats["damage"] = 10
					end
				end	
			end

			#sleep for 1 ms
			sleep(0.001)
		end
		
		@server.close
		
		if $debug then puts "STOPPED LISTENING THREAD..." end
	end
	
	#this sends the login request to the server.
	#returns the result of the attempt (true or false)
	def send_login(name,clss)		
		if $debug then puts "SENDING LOGIN REQUEST TO SERVER..." end
		#@send_message = "{\"message_id\":\"get_map\"}\n"
		msg = "{\"message_id\":\"login\",\"name\":\"" + name + "\",\"class\":\"" + clss + "\"}\n"
		if $debug then puts msg end
		@server.puts msg
		@got_response = false
	end
		
	def update
		$event_queue.each do |event|
			case event
				when Events::KeyReleased
					key = event.key
					if key == :escape
						msg = "{\"message_id\":\"logout\"}\n"
						@server.puts msg
						$currentstate = "mainmenu"
					elsif key == :left
						try_move(-1,0)
					elsif key == :right
						try_move(1,0)
					elsif key == :up
						try_move(0,-1)
					elsif key == :down
						try_move(0,1)
					end				
					
				when Events::QuitRequested
					msg = "{\"message_id\":\"logout\"}\n"
					@server.puts msg
					$should_run = false
			end
		end
  
	end
	
	def draw
		#fill the screen with a background color
		@screen.fill([0,0,0],[0,0,@screen.w(),@screen.h()])
		
		if @map.map_loaded == false
			text = "WAITING FOR SERVER..."
			text_surface = @fontStats.render_utf8 text, true, [255,255,0]
			rt = text_surface.make_rect
			rt.topleft = [@screen.w / 2 - rt.w / 2, @screen.h / 2 - rt.h]
			text_surface.blit @screen, rt
			return
		end
		
		@map.draw @screen
		
		#draw the stats
		if $player_name.length > 0 && @player_stats != nil
		  xp = @player_stats["xp"]
			dam = @player_stats["damage"]
			dex = @player_stats["dexterity"]
			dod = @player_stats["dodge"]
			dur = @player_stats["durability"]
			maxdur = @player_stats["max_durability"]
			lev = @player_stats["level"]
		
		
			text = "XP: " + xp.to_s() + " DAM: " + dam.to_s() + "  DEX: " + dex.to_s() + "  DOD: " + dod.to_s() + "  DUR: " + dur.to_s() + "(" + maxdur.to_s() + ")"
			text_surface = @fontStats.render_utf8 text, true, [255,255,0]
			rt = text_surface.make_rect
			rt.topleft = [10, @screen.h - @fontStats.size_text("W")[1]]
			text_surface.blit @screen, rt
		end
	end
	
	def set_player_sprite name
		$player_image = name
	end
	
	def try_move dX, dY
		#if @in_move == true then return end
		
		@in_move = true
		
		if @map.player == nil
			@in_move = false
			return
		end
		
		#get the tile at the position the character
		#would move to.
		x = @map.player["x"] + dX
		y = @map.player["y"] + dY
		
		#make sure the space is within the bounds
		if x < 0 || y < 0 || x >= @map.w || y >= @map.h
			@in_move = false
			return
		end
		
		@attempt_move[0] = dX
		@attempt_move[1] = dY
		
		if dX == -1 && dY == 0
			dir = "W"
		elsif dX == 0 && dY == -1
			dir = "N"
		elsif dX == 0 && dY == 1
			dir = "S"
		elsif dX == 1 && dY == 0
			dir = "E"
		end
		
		#send message to server
		#{"message_id":"move","direction":"dir"}
		msg = "{\"message_id\":\"move\",\"direction\":\"" + dir + "\"}\n"
		if $debug then puts "SENDING: " + msg end
		@server.puts msg
	end
	
end